package com.softaria.windows.widgets;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.DecoratedTabPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.softaria.windows.styles.WorkPanelStyles;

/**
 * Represents work are in {@link Desktop} May be managed with
 * {@link com.softaria.windows.logic.PerspectiveManager}
 * 
 * @author Roman M Kuzmin (roman@softaria.com)
 * 
 */
public class TabbedWorkPanel extends DecoratedTabPanel implements WorkPanelStyles {

  private Tab selectedTab = null;

  /**
   * Represents Tab in TabbedWorkPanel
   * 
   * @author Roman M Kuzmin (roman@softaria.com)
   * 
   */
  public class Tab {

    private static final String IMAGES_CLOSE_GIF = "windows/images/close.gif";

    private Image closeImage;
    private AbsolutePanel panel;
    private Grid border;
    private ResizeListenerRegistrator resizeListenerRegistrator;

    private List<Command> userSelectionListeners = new ArrayList<Command>(10);

    private boolean programCausedEventsMode = false;

    public Tab(String name, ResizeListenerRegistrator resizeListenerRegistrator,
        boolean showCloseButton) {

      this.resizeListenerRegistrator = resizeListenerRegistrator;

      setLineEnabled(true);

      final HorizontalPanel horPanel = new HorizontalPanel();
      HTML tabName = new HTML("<nobr>" + name + "</nobr>");
      tabName.setStylePrimaryName(MAIN_TAB_STYLE);

      horPanel.add(tabName);

      if (showCloseButton) {
        closeImage = new Image(GWT.getModuleBaseURL() + IMAGES_CLOSE_GIF);
        closeImage.getElement().getStyle().setProperty("cursor", "pointer");
        horPanel.add(closeImage);
      }

      panel = new AbsolutePanel();
      panel.setHeight("100%");
      panel.setWidth("100%");

      border = new Grid(3, 3);
      border.setCellPadding(0);
      border.setCellSpacing(0);
      border.setBorderWidth(0);

      border.setStylePrimaryName(WP);

      border.getRowFormatter().addStyleName(0, WP_ROW_TOP);
      border.getRowFormatter().addStyleName(1, WP_ROW_CONTENT);
      border.getRowFormatter().addStyleName(2, WP_ROW_BOTTOM);

      border.getCellFormatter().addStyleName(0, 0, WP_CELL_TL);
      border.getCellFormatter().addStyleName(0, 1, WP_CELL_TM);
      border.getCellFormatter().addStyleName(0, 2, WP_CELL_TR);
      border.getCellFormatter().addStyleName(1, 0, WP_CELL_CL);
      border.getCellFormatter().addStyleName(1, 1, WP_CELL_CM);
      border.getCellFormatter().addStyleName(1, 2, WP_CELL_CR);
      border.getCellFormatter().addStyleName(2, 0, WP_CELL_BL);
      border.getCellFormatter().addStyleName(2, 1, WP_CELL_BM);
      border.getCellFormatter().addStyleName(2, 2, WP_CELL_BR);

      border.setWidget(0, 0, createXGif());
      border.setWidget(0, 1, createXGif());
      border.setWidget(0, 2, createXGif());
      border.setWidget(1, 0, createXGif());
      border.setWidget(1, 1, panel);
      border.setWidget(1, 2, createXGif());
      border.setWidget(2, 0, createXGif());
      border.setWidget(2, 1, createXGif());
      border.setWidget(2, 2, createXGif());

      add(border, horPanel);

      addSelectionHandler(new SelectionHandler<Integer>() {

        public void onSelection(SelectionEvent<Integer> event) {

          if (programCausedEventsMode)
            return;

          if (event.getSelectedItem() == getWidgetIndex(border)) {
            // it is me !!! and event caused by user's click on tab
            for (Command listener : userSelectionListeners) {
              listener.execute();
            }
          }

        }

      });

    }

    private Image createXGif() {
      Image xGif = new Image(GWT.getModuleBaseURL() + "windows/images/x.gif");
      xGif.setStylePrimaryName(WP_BORDER_INLINE);

      return xGif;
    }

    /**
     * Adds listener which should be called when user selects tab (Tab will be
     * selected before this listener will be called)
     * 
     * @param listener
     */
    public void addUserSelectionListener(Command listener) {
      userSelectionListeners.add(listener);
    }

    /**
     * Adds listener which will be called when user clicks close button. Note
     * that tab will NOT be closed automatically in this case! You should do it
     * in listener, when required
     * 
     * @param listener
     */
    public void addCloseButtonListener(ClickHandler listener) {
      closeImage.addClickHandler(listener);
    }

    /**
     * Selects (activates) tab
     */
    public void select() {

      if (this != selectedTab) {
        // This code exists to prevent cycle
        // because select() raise event and event handler calls select()
        // (indirectly) again
        selectedTab = this;

        // Prevent the following situation:
        // One calls WindowManager.openPerspectiveOrView
        // It lead to call this method
        // which calls GWT's selectTab,
        // that throws "SELECTED" event which is identical to event, caused by
        // user's
        // click on tab. Without skipEvents flag we will handle this event and
        // will
        // call it's handler, which is , yes, really -
        // WindowManager.openPerspectiveOrView :-)
        programCausedEventsMode = true;
        selectTab(getWidgetIndex(border));
        programCausedEventsMode = false;

      }
    }

    /**
     * Removes tab and all its content from TabbedWorkPanel
     */
    public void delete() {
      remove(border);
      int tabCount = getTabBar().getTabCount();
      if (tabCount == 0) {
        setLineEnabled(false);
      }
    }

    /**
     * 
     * @return panel where widgets (e.g. Frame s) should be placed
     */
    public AbsolutePanel getPanel() {
      return panel;
    }

    public void updateSize() {
      if (resizeListenerRegistrator != null) {
        resizeListenerRegistrator.notifyViewResized(panel);
      }

    }

  }

  public TabbedWorkPanel() {
    super();
    setStyleName(WORKPANEL_STYLE);
    getElement().setId(WORK_PANEL_ID);

    setLineEnabled(false);

  }

  private void setLineEnabled(boolean enabled) {
    if (enabled) {
      removeStyleName(WP_HIDE_LINE);
    } else {
      addStyleName(WP_HIDE_LINE);
    }

  }

  /**
   * Creates new Tab on panel
   * 
   * @param name
   *          - label to be placed on tab
   * @return
   */
  public Tab createNewTab(String name) {

    return new Tab(name, null, true);
  }

  /**
   * Creates new Tab on panel
   * 
   * @param name
   *          - label to be placed on tab
   * @return
   */
  public Tab createNewTab(String name, ResizeListenerRegistrator rlreg) {

    return new Tab(name, rlreg, true);
  }

  /**
   * Creates new Tab on panel
   * 
   * @param name
   *          - label to be placed on tab
   * @return
   */
  public Tab createNewTab(String name, ResizeListenerRegistrator rlreg, boolean showCloseButton) {

    return new Tab(name, rlreg, showCloseButton);
  }

}
